/**
 * @file main.cpp
 * @author iam002
 * @brief 主程序，实现程序调用接口
 * @version 0.1
 * 
 * @copyright Copyright (c) 2023
 * 
 */
#include <iostream>
#include "funcsigner.h"

#ifdef _MSV_VER
#include <Windows.h>
#endif

const char * HELP_STR = 
    "本程序功能:\n" \
    "    根据函数文件的注释信息，自动生成函数签名文件(json). 函数签名文件能够允许在编辑器调用这些自定义的函数\n" \
    "的时候具备代码提示功能，提升编程体验.\n" \
    "\n" \
    "调用方法:\n\n" \
    "    signfun.exe <DirPath> [-ag -] [-op *] [-ver 1.0.0] [-info on/off]  [-kind required] [-type numeric]" \
    "\n" \
    "\n其中，必须指定目标文件夹的路径<DirPath>，其他几项为可选项:\n" \
    "    -ag   是参数标识符，默认为  -\n" \
    "    -op   是选项标识符，默认为  *\n" \
    "    -ver  是签名文件的版本信息，默认为 1.0.0\n" \
    "    -log  是否输出详细信息，默认为 on \n" \
    "    -kind 设置默认参数kind，默认为 required，不建议修改\n" \
    "    -type 设置默认参数type，默认为 numeric，不建议修改 \n" \
    "\n" \
    "Matlab 相关链接(推荐阅读):\n" \
    "\thttps://ww2.mathworks.cn/help/matlab/matlab_prog/customize-code-suggestions-and-completions.html\n" \
   "\thttps://ww2.mathworks.cn/help/matlab/matlab_prog/customize-code-suggestions-and-completions.html\n" \
   "\thttps://ww2.mathworks.cn/help/matlab/ref/arguments.html\n" \
   "\thttps://gitee.com/iam002/funcsign.git\n" \
    "\n";

enum class OrderType {
    Argsym,
    Optsym,
    Version,
    Verbose,
    Defkind,
    Deftype,
    Error
};

OrderType getState(const char * order_str)
{
    if (strcmp(order_str, "-ag") == 0) {
        return OrderType::Argsym;
    }
    else if (strcmp(order_str, "-op") == 0) {
        return OrderType::Optsym;
    }
    else if (strcmp(order_str, "-ver") == 0) {
        return OrderType::Version;
    }
    else if (strcmp(order_str, "-log") == 0) {
        return OrderType::Verbose;
    }
    else if (strcmp(order_str, "-kind") == 0) {
        return OrderType::Defkind;
    }
    else if (strcmp(order_str, "-type") == 0) {
        return OrderType::Deftype;
    }
    else {
        return OrderType::Error;
    }
    
}

int main(int argc, char** argv)
{
    FuncSigner signer;
    std::string argsym;
    std::string optsym;
    std::string version;
    bool verbose;
    std::string defkind;
    std::vector<std::string> deftype;

#ifdef _MSV_VER
    SetConsoleOutputCP(65001);
#endif

    if (argc == 1) {
        std::cout << HELP_STR << std::endl;
        return 0;
    }
    else if (argc > 2){
        for (int i = 2; i < argc;) {
            OrderType ord = getState(argv[i]);
            if (ord == OrderType::Argsym) {
                int last_id = i + 1;
                while (last_id < argc && ((strlen(argv[last_id]) == 1 && argv[last_id][0] == '-') || argv[last_id][0] != '-')) {
                    last_id ++;
                }
                if (last_id - 1 == i) {
                    std::cerr << "Error: `-ag` No parameter was matched!" << std::endl;
                    return -1;
                }
                else if (last_id - 2 > i ) {
                    std::cerr << "Warn: `-ag` Too many match parameters!" << std::endl;
                }
                argsym = argv[last_id - 1];
                i = last_id;
                signer.setArgSym(argsym.c_str());
                std::cout << "Set Argument Symbol: " << argsym << std::endl;
            }
            else if (ord == OrderType::Optsym) {
                int last_id = i + 1;
                while (last_id < argc && ((strlen(argv[last_id]) == 1 && argv[last_id][0] == '-') || argv[last_id][0] != '-')) {
                    last_id ++;
                }
                if (last_id - 1 == i) {
                    std::cerr << "Error: `-op` No parameter was matched!" << std::endl;
                    return -1;
                }
                else if (last_id - 2 > i ) {
                    std::cerr << "Warn: `-op` Too many match parameters!" << std::endl;
                }
                optsym = argv[last_id - 1];
                i = last_id;
                signer.setOptSym(optsym.c_str()); 
                std::cout << "Set Option Symbol: " << optsym << std::endl;
            }
            else if (ord == OrderType::Version) {
                int last_id = i + 1;
                while (last_id < argc && ((strlen(argv[last_id]) == 1 && argv[last_id][0] == '-') || argv[last_id][0] != '-')) {
                    last_id ++;
                }
                if (last_id - 1 == i) {
                    std::cerr << "Error: `-ver` No parameter was matched!" << std::endl;
                    return -1;
                }
                else if (last_id - 2 > i ) {
                    std::cerr << "Warn: `-ver` Too many match parameters!" << std::endl;
                }
                version = argv[last_id - 1];
                i = last_id;
                signer.setVersion(version.c_str());
                std::cout << "Set Version: " << version << std::endl;
            }
            else if (ord == OrderType::Verbose) {
                int last_id = i + 1;
                while (last_id < argc && ((strlen(argv[last_id]) == 1 && argv[last_id][0] == '-') || argv[last_id][0] != '-')) {
                    last_id ++;
                }
                if (last_id - 1 == i) {
                    std::cerr << "Error: `-log` No parameter was matched!" << std::endl;
                    return -1;
                }
                else if (last_id - 2 > i ) {
                    std::cerr << "Warn: `-log` Too many match parameters!" << std::endl;
                }
                if ( strcmp(argv[last_id - 1], "on") || strcmp(argv[last_id - 1], "On") || strcmp(argv[last_id - 1], "ON")
                  || strcmp(argv[last_id - 1], "yes") || strcmp(argv[last_id - 1], "Yes") || strcmp(argv[last_id - 1], "YES")
                  || strcmp(argv[last_id - 1], "y") || strcmp(argv[last_id - 1], "Y") || strcmp(argv[last_id - 1], "1")
                  || strcmp(argv[last_id - 1], "true") || strcmp(argv[last_id - 1], "True") || strcmp(argv[last_id - 1], "TRUE")
                  ) {
                    verbose = true;
                }
                else if ( strcmp(argv[last_id - 1], "off") || strcmp(argv[last_id - 1], "Off") || strcmp(argv[last_id - 1], "OFF")
                  || strcmp(argv[last_id - 1], "no") || strcmp(argv[last_id - 1], "No") || strcmp(argv[last_id - 1], "NO")
                  || strcmp(argv[last_id - 1], "n") || strcmp(argv[last_id - 1], "N") || strcmp(argv[last_id - 1], "0")
                  || strcmp(argv[last_id - 1], "false") || strcmp(argv[last_id - 1], "False") || strcmp(argv[last_id - 1], "FALSE")
                  ) {
                    verbose = false;
                }
                else {
                    std::cerr << "Error: `-log` Ivalid parameters!" << std::endl;
                    return -1;
                }
                i = last_id;
                signer.setVerbose(verbose);
            }
            else if (ord == OrderType::Defkind) {
                int last_id = i + 1;
                while (last_id < argc && ((strlen(argv[last_id]) == 1 && argv[last_id][0] == '-') || argv[last_id][0] != '-')) {
                    last_id ++;
                }
                if (last_id - 1 == i) {
                    std::cerr << "Error: `-kind` No parameter was matched!" << std::endl;
                    return -1;
                }
                else if (last_id - 2 > i ) {
                    std::cerr << "Warn: `-kind` Too many match parameters!" << std::endl;
                }
                defkind = argv[last_id - 1];
                i = last_id;
                signer.setDefaultKind(defkind);
            }
            else if (ord == OrderType::Deftype) {
                int last_id = i + 1;
                while (last_id < argc && ((strlen(argv[last_id]) == 1 && argv[last_id][0] == '-') || argv[last_id][0] != '-')) {
                    last_id ++;
                }
                if (last_id - 1 == i) {
                    std::cerr << "Error: `-kind` No parameter was matched!" << std::endl;
                    return -1;
                }
                deftype.clear();
                for (int k = i + 1; k < last_id; ++k) {
                    deftype.push_back(argv[k]);
                }
                i = last_id;
                signer.setDefaultType(deftype);
            }
            else {
                std::cerr << "Warn: Invalid order!" << std::endl;
                i ++;
            }
        }
    }
    signer.generate(argv[1]);
    
    return 0;
}
